#pragma once
#include <windows.h>
#include "rendermaterial.h"
#include "rendertexture.h"
#include "vertexdeclaration.h"
#include "vertexbuffer.h"
#include "indexbuffer.h"
#include "shader.h"
#include "core/fixedvector.h"
#include "core/hashmap.h"

#include "rendermesh.h"
#include "rendernode.h"
#include "renderhierarchy.h"
struct rendernode_t;

struct rendercontext_t
{
	float4x4 camera_matrix;
	float4x4 projection_matrix;
};

#define MAX_LIGHT_COUNT 4
struct global_shader_data_t
{
	float4x4 camera_mtx;
	float4x4 proj_mtx;
	float4x4 viewproj_mtx;
	float4x4 world_mtx;
	float4 model_color;
	float4 directional_light;
	float2	stereo_direction;
	float2 dummy;
	struct
	{
		float4 centerradius;
		float4 color;
	} light[MAX_LIGHT_COUNT];

	global_shader_data_t()
	{
		ZeroMemory(this,sizeof(global_shader_data_t));
		camera_mtx.identity();
		viewproj_mtx=get_projection_matrix(DEG2RAD*45,3.0f/4,1,1000);
//		viewproj_mtx.transpose();
		world_mtx.identity();
		directional_light=float4(0,0,-1,0);
		model_color=float4(1,1,1,1);
		stereo_direction.set(0,0);

	}
};

struct rendersystem_t
{
	rendersystem_t(HWND hwnd);
	~rendersystem_t();
	static void init(HWND hwnd);
	static void exit();
	void render(rendercontext_t* ctx=NULL);
#ifdef LEO_DESIGNER
	void render(const float4x4& cameramtx, const float4x4& projmtx);
#endif
	void flushbuffers();

	void loadglobals();

	unsigned num_lights;
	void set_light(const float3& center, float radius, const float4& color);

	HDC hdc;
//	uint32 textureid;
//	rendertexture_t* testtexture;

	float aspect;
	float fov;

	struct text_struct_t
	{
		float x;
		float y;
		string text;
	};

	fixedvector<text_struct_t,1000> rendertexts;

	static hashcontainer_t<rendertexture_t,1024,1024> textures;
	static hashcontainer_t<shader_t,1024,1024> shaders;
	static hashcontainer_t<rendermaterial_t,1024,1024> materials;
	static hashcontainer_t<vertexdeclaration_t,16,16> vertexdeclarations;
	static hashcontainer_t<renderhierarchy_t,16384,16384> objects;

#ifdef LEO_DESIGNER
	bool selection_on;
#endif


	static shader_t* get_shader(const stringhash& name)
	{
		return shaders.get(name);
	}

	static rendermaterial_t* get_material(const stringhash& name)
	{
		return materials.get(name);
	}

	static vertexdeclaration_t* get_vdecl(const stringhash& name)
	{
		return vertexdeclarations.get(name);
	}

	static rendertexture_t* get_texture(const stringhash& name);
	static bool get_3d_object(renderhierarchy_t&,const stringhash& name);
	void set_object_data();
	void set_object_world_matrix(const float4x4&);

	fixedvector<renderhierarchy_t*,16384> renderobjects;
	fixedvector<renderobject_t*,16384> custom_renderobjects;

	indexbuffer_t quadib;
	uint32 dynamic_vb_id;
	uint32 dynamic_offset;

	void* lock_dynamic_vb(uint32 size,uint32& offset);
	void unlock_dynamic_vb();

	void render_object(renderhierarchy_t* node)
	{
		renderobjects.push_back(node);
	}

	void render_custom_object(renderobject_t* node)
	{
		custom_renderobjects.push_back(node);
	}

	struct debug_text_t
	{
		string text;
		int x,y;
		float depth;
		int size;
		float4 color;

		debug_text_t(){}
		debug_text_t(int _x, int _y,const string& _text,const float4& _color, int _size,float _depth):x(_x),y(_y),size(_size),text(_text),color(_color),depth(_depth){}
	};
	vector<debug_text_t> text_array;
	vertexbuffer_t textvb;
	uint32 textcharnum;

	void print(int x, int y,const string& text, const float4& color=float4(1,1,1,1), int size=32,float depth=0)
	{
		text_array.push_back(debug_text_t(x,y,text,color,size,depth));
	}
	void setup_textdraw();
	void draw_texts();

	bool captureisvan;



	struct debug_line_t
	{
		float3 startpos;
		float4 startcolor;
		float3 endpos;
		float4 endcolor;
	};

	vector<debug_line_t> line_array;
	vertexbuffer_t linevb;
	void draw_line(const float3& startpos,const float3& endpos, const float4& startcolor=float4(1,1,1,1), const float4& endcolor=float4(1,1,1,1))
	{
		debug_line_t dl={startpos,startcolor,endpos,endcolor};
		line_array.push_back(dl);
	}

	void setup_linedraw();
	void draw_lines();


	global_shader_data_t global_shader_data;
	uint32 globalshaderdataid;
	uint32 whitetextureid;
	uint32 globalsamplerstateid;

	float4x4 projection_matrix;

	int screen_size_horizontal;
	int screen_size_vertical;

	HWND main_hwnd;
	void on_resize(bool caption=false);

	bool textdraw_enabled;
};

uint32 loadCompressedTexture( const char* filename );

extern rendersystem_t* RSYS;